/**
 * STFractalGenerator.java
 * @author: liuex
 * 2008-1-6 ����03:34:33
 *
 * note: 
 */
package lex.fractal;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.Line2D;

import lex.fractal.algorithm.Fractal;

/**
 * In 1915, Polish mathematician Waclaw Sierpinski described a fractal that is
 * an example of a self-similar set. This fractal is known as the Sierpinski
 * triangle, but is also referred to as the Sierpinski gasket.<br>
 * The algorithm below recursively generates the Sierpinski triangle: <br>
 * 1.Start with an equilateral triangle whose base is parallel to the horizontal
 * axis. (In practice, any triangle with any orientation will work.) <br>
 * 2.Shrink the triangle by 50%, make three copies, and translate the copies so
 * that each triangle touches the other two triangles at a corner. <br>
 * 3.Assume that each shrunken copy is the original equilateral triangle and
 * apply the previous steps to each copy.
 */
public class SierpinskiTtriangleFractal implements Fractal {
	private final static int MAX_DEPTH = 5;
	private final static int OFFSET = 10;
	private Line2D line = new Line2D.Double(0.0, 0.0, 0.0, 0.0);
	private Stroke stroke = new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);

	public String getName() {
		return "Sierpinski triangle";
	}

	public void generate(Graphics2D g, int depth, int width, int height) {
		st(width / 2, OFFSET, OFFSET, height - 1 - OFFSET, width - 1 - OFFSET, height - 1 - OFFSET, depth, g);
	}

	public int getMaximalDepth() {
		return MAX_DEPTH;
	}

	private void st(int x1, int y1, int x2, int y2, int x3, int y3, int depth, Graphics2D g) {
		if (depth <= 0) {
			g.setStroke(stroke);
			line.setLine(x1, y1, x2, y2);
			g.draw(line);
			line.setLine(x2, y2, x3, y3);
			g.draw(line);
			line.setLine(x3, y3, x1, y1);
			g.draw(line);
		} else {
			int x4 = (x1 + x2) / 2;
			int y4 = (y1 + y2) / 2;
			int x5 = (x2 + x3) / 2;
			int y5 = (y2 + y3) / 2;
			int x6 = (x1 + x3) / 2;
			int y6 = (y1 + y3) / 2;
			st(x1, y1, x4, y4, x6, y6, depth - 1, g);
			st(x4, y4, x2, y2, x5, y5, depth - 1, g);
			st(x6, y6, x5, y5, x3, y3, depth - 1, g);
		}
	}
}
